home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Nebula 1
/
Nebula One.iso
/
Misc
/
SciCalc1.1
/
Source
/
OperatorStack.m
< prev
next >
Wrap
Text File
|
1994-04-24
|
10KB
|
336 lines
/***(OperatorStack.m)**********************************************************
*H* Push down stack for numeric operators V0.0, 09-FEB-91 *
*C* V0.0 09-FEB-91 Initial version --MDM *
******************************************************************************/
/* Standard C Library includes */
#import <stdio.h> /* Standard I/O functions and definitions */
#import <stdlib.h> /* Standard C memory allocation prototypes */
#import "OperatorStack.h" /* OperatorStack interface specification */
/* Class Private Data */
typedef struct OSoperator
{
char *name;
int precedence;
int n_operands;
} OToperator;
/* Table describing each operator */
static OToperator OVopTable[OPCODE_OpCodes] =
{
{ "Equals", 4, 1 },
{ "Plus", 14, 2 },
{ "Minus", 14, 2 },
{ "Multiply", 15, 2 },
{ "Divide", 15, 2 },
{ "OpenParen", 5, 0 },
{ "CloseParen", 6, 0 },
{ "SIN", 17, 1 },
{ "ASIN", 17, 1 },
{ "SINH", 17, 1 },
{ "ASINH", 17, 1 },
{ "COS", 17, 1 },
{ "ACOS", 17, 1 },
{ "COSH", 17, 1 },
{ "ACOSH", 17, 1 },
{ "TAN", 17, 1 },
{ "ATAN", 17, 1 },
{ "TANH", 17, 1 },
{ "ATANH", 17, 1 },
{ "EXP", 17, 1 },
{ "LN", 17, 1 },
{ "LOG", 17, 1 },
{ "10^X", 17, 1 },
{ "X^Y", 16, 2 },
{ "XrootY", 16, 2 },
{ "XSquared", 17, 1 },
{ "SqrRoot", 17, 1 },
{ "1overX", 17, 1 },
{ "Factorial", 17, 1 },
{ "Pi", 17, 1 },
{ "Modify", 15, 2 },
{ "Integer", 17, 1 },
{ "And", 10, 2 },
{ "Or", 8, 2 },
{ "Not", 17, 1 },
{ "Xor", 9, 2 },
{ "LShift", 17, 1 },
{ "RShift", 17, 1 }
};
@implementation OperatorStack
/* Private Object Wide Definitions */
#define OCnullStack (OToperStackItem *) 0
/******************************************************************************
* INSTANCE METHOD:- init *
* Initialize a new instance of a OperatorStack class. *
******************************************************************************/
- init
{/* BEGIN:-init */
self = [super init];
OVstackTop = OCnullStack;
OVstackSize = 0;
return self;
}/* END:-init */
/******************************************************************************
* INSTANCE METHOD:- free *
* All data currently on the OperatorStack is poped and freed, returning the *
* allocated memory back to the system pool. *
******************************************************************************/
- free
{ /* Local Variables */
OToperStackItem *tmp_blink;
/* BEGIN free */
while (OVstackTop != OCnullStack)
{/* Get pointer to lower stack item and free top item */
tmp_blink = OVstackTop->blink;
free( (char *) OVstackTop );
OVstackTop = tmp_blink;
OVstackSize = 0;
}
/* Request super class to perform its free method */
return [super free];
}/* END free */
/******************************************************************************
* INSTANCE METHOD:- ClearStack *
* Pop and free each element on the stack until the stack is empty. *
******************************************************************************/
- ClearStack
{ /* Local Variables */
OToperStackItem *tmp_blink;
/* BEGIN Clear */
while ( OVstackTop )
{/* Stack is not empty, free top item */
tmp_blink = OVstackTop->blink;
free ( (char *) OVstackTop );
OVstackTop = tmp_blink;
}
OVstackSize = 0;
return self;
}/* END ClearStack */
/******************************************************************************
* INSTANCE METHOD:- ComparePrecedence *
* Compares the precedence of opcode against the opcode on the top of the *
* stack and returns the difference in the result argument. The comparison is *
* made by subtracting the numerical precedence value of the supplied opcode *
* with that of the opcode on the top of the stack. If the stack is empty the *
* supplied opcode is compared against a precedence value of zero. The *
* returned value has the following meanings: *
* result >= 1: opcode has higher precedence stack top opcode. *
* result == 0: opcode and stack top opcode are of equal precedence. *
* result <= 1: opcode is of lesser precedence than stack top opcode. *
******************************************************************************/
- ComparePrecedence: (int) opcode: (int *) result
{/* BEGIN ComparePrecedence */
if (opcode < 0 || opcode > OPCODE_LastOpCode)
return nil; /* return failure status */
if ( OVstackSize > 0 )
/* Stack is not empty, use precedence of opcode on stack top */
*result = OVopTable[opcode].precedence - OVopTable[OVstackTop->opcode].precedence;
else
/* Stack is empty, assume a precedence value of zero */
*result = OVopTable[opcode].precedence - 0;
return self;
}/* END ComparePrecedence */
/******************************************************************************
* INSTANCE METHOD:- GetSize *
* Return the current number of items in the Value Stack. *
******************************************************************************/
- (unsigned long) GetSize
{/* BEGIN GetSize */
return OVstackSize;
}/* END GetSize */
/******************************************************************************
* INSTANCE METHOD:- NumberOfOperands *
* Return the operands that the given opcode requires. *
******************************************************************************/
- NumberOfOperands :(int)opcode :(int*)noperands
{/* BEGIN NumberOfOperands */
if ( opcode >= OPCODE_Equals && opcode <= OPCODE_LastOpCode )
{/* The caller supplied a legal opcode, return successfully */
*noperands = OVopTable[opcode].n_operands;
return self;
}
else
/* The caller supplied an invalid opcode, return with error status */
return nil;
}/* END NumberOfOperands */
/******************************************************************************
* INSTANCE METHOD:- Peek *
* Return the value on the top of the stack without removing it from the *
* stack. *
******************************************************************************/
- Peek: (int *) opcode
{/* BEGIN Peek */
if ( OVstackTop )
{/* The stack is not emptry */
*opcode = OVstackTop->opcode;
return self; /* succesful status */
}
else
{/* Report illegal reference to standard error */
#ifdef DEBUG
fprintf(stderr, "OperatorStack: Peek on empty stack returning -1\n");
#endif
*opcode = -1;
return nil; /* failure status */
}
}/* END Peek */
/******************************************************************************
* INSTANCE METHOD:- Pop *
* Return the value opcode on the top of the stack and free top stack item. *
******************************************************************************/
- Pop: (int *) opcode
{ /* Local Variables */
OToperStackItem *tmp_blink;
/* BEGIN Pop */
if ( OVstackTop )
{/* Stack is not empty, free top item and return top value */
*opcode = OVstackTop->opcode;
tmp_blink = OVstackTop->blink;
free ( (char *) OVstackTop );
OVstackTop = tmp_blink;
OVstackSize--;
return self;
}
else
{/* Stack is empty report error, return -1 */
#ifdef DEBUG
fprintf(stderr, "OperatorStack: Pop on empty stack returning -1\n");
#endif
*opcode = -1;
return nil; /* failure status */
}
}/* END Pop */
/******************************************************************************
* INSTANCE METHOD:- Push *
* Push an opcode value on the stack. We allocate a new stack item setting *
* its opcode field to the supplied opcode value, and its blink field to point *
* to the current stack top. If a new stack item cannot be allocated an error *
* message is written to stderr. *
******************************************************************************/
- Push: (int) opcode
{ /* Local Variables */
OToperStackItem *new_item;
/* BEGIN Push */
/* Allocate a new stack item */
new_item = (OToperStackItem *) malloc(sizeof(OToperStackItem));
if ( new_item )
{/* New stack item allocated, initialize and link in new stack top */
new_item->opcode = opcode;
new_item->blink = OVstackTop;
OVstackTop = new_item;
OVstackSize++;
return self;
}
else
{/* Allocation failed, report error to stderr */
#ifdef DEBUG
fprintf(stderr, "OperatorStack: Push allocation failure\n");
#endif
return nil;
}
}/* END Push */
/******************************************************************************
* INSTANCE METHOD:- PrintStack *
* Print out the contents of the stack to standard output. *
******************************************************************************/
- PrintStack
{ /* Local Variables */
OToperStackItem *trace_link;
int oti; /* operator table index */
long level;
/* BEGIN PrintStack */
if ( OVstackTop )
{/* The stack is not empty so dump its contents */
trace_link = OVstackTop;
level = 0;
while ( trace_link )
{/* Not at bottom, print this item */
oti = trace_link->opcode;
#ifdef DEBUG
printf("%s\t%d\t%d\t:(%ld)\n",
OVopTable[oti].name,
OVopTable[oti].precedence,
OVopTable[oti].n_operands,
level--);
#endif
trace_link = trace_link->blink;
}
}
else
{/* Stack is empty so print a message */
#ifdef DEBUG
printf("OperatorStack: stack empty\n");
#endif
}
return self;
}/* END PrintStack */
@end /* ValueStack Implementation */